home *** CD-ROM | disk | FTP | other *** search
- /* ------------- textbox.c ------------ */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include "dflat.h"
-
- static char *GetTextLine(WINDOW wnd, int selection);
-
- static int HScrolling = FALSE;
- static int VScrolling = FALSE;
-
- int TextBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
- {
- int mx = (int) p1 - GetLeft(wnd);
- int my = (int) p2 - GetTop(wnd);
- switch (msg) {
- case CREATE_WINDOW:
- wnd->wlines = wnd->wtop = wnd->wleft =
- wnd->textlen = wnd->textwidth = 0;
- wnd->text = NULL;
- wnd->HScrollBox = wnd->VScrollBox = 1;
- ClearBlock(wnd);
- break;
- case ADDTEXT: {
- /* ======== need to assure that length !> 64K ======= */
- int adln = strlen((char *)p1)+2;
- if (wnd->text != NULL) {
- int txln = strlen(wnd->text);
- if (txln+adln > wnd->textlen) {
- wnd->text = realloc(wnd->text, txln+adln);
- wnd->textlen = txln+adln-1;
- }
- }
- else {
- wnd->text = malloc(adln);
- *wnd->text = '\0';
- wnd->textlen = adln-1;
- }
- strcat(wnd->text, (char*) p1);
- strcat(wnd->text, "\n");
- wnd->wlines++;
- wnd->textwidth = max(adln, wnd->textwidth);
- break;
- }
- case SETTEXT: {
- char *cp, *cp1;
- SendMessage(wnd, CLEARTEXT, 0, 0);
- wnd->text = cp = cp1 = (void *) p1;
- wnd->textlen = max(strlen(cp)+1, (int) p2);
- while ((cp = strchr(cp, '\n')) != NULL) {
- wnd->wlines++;
- cp++;
- wnd->textwidth = max(wnd->textwidth, (int)(cp-cp1));
- cp1 = cp;
- }
- break;
- }
- case CLEARTEXT:
- if (wnd->text != NULL)
- free(wnd->text);
- wnd->text = NULL;
- wnd->textlen = 0;
- wnd->wlines = 0;
- wnd->textwidth = 0;
- wnd->wtop = wnd->wleft = 0;
- ClearBlock(wnd);
- break;
- case SETFOCUS:
- if (!p1 && isMultiLine(wnd))
- ClearBlock(wnd);
- break;
- case KEYBOARD:
- if (WindowMoving || WindowSizing)
- break;
- switch ((int) p1) {
- case UP:
- if (wnd->wtop)
- SendMessage(wnd, SCROLL, FALSE, 0);
- return TRUE;
- case DN:
- if (wnd->wtop+ClientHeight(wnd) < wnd->wlines)
- SendMessage(wnd, SCROLL, TRUE, 0);
- return TRUE;
- case FWD:
- SendMessage(wnd, HORIZSCROLL, TRUE, 0);
- return TRUE;
- case BS:
- SendMessage(wnd, HORIZSCROLL, FALSE, 0);
- return TRUE;
- case PGUP:
- if (wnd->wtop) {
- wnd->wtop -= ClientHeight(wnd);
- if (wnd->wtop < 0)
- wnd->wtop = 0;
- SendMessage(wnd, PAINT, 0, 0);
- return TRUE;
- }
- return TRUE;
- case PGDN:
- if (wnd->wtop+ClientHeight(wnd) < wnd->wlines) {
- wnd->wtop += ClientHeight(wnd);
- if (wnd->wtop > wnd->wlines-ClientHeight(wnd))
- wnd->wtop = wnd->wlines-ClientHeight(wnd);
- SendMessage(wnd, PAINT, 0, 0);
- return TRUE;
- }
- return TRUE;
- case HOME:
- if (wnd->wtop || wnd->wleft) {
- wnd->wtop = wnd->wleft = 0;
- SendMessage(wnd, PAINT, 0, 0);
- }
- return TRUE;
- case END:
- if (wnd->wtop+ClientHeight(wnd) < wnd->wlines) {
- wnd->wtop = wnd->wlines-ClientHeight(wnd);
- wnd->wleft = 0;
- SendMessage(wnd, PAINT, 0, 0);
- }
- return TRUE;
- default:
- break;
- }
- break;
- case LEFT_BUTTON:
- if (WindowSizing || WindowMoving)
- return FALSE;
- if (TestAttribute(wnd, VSCROLLBAR) && (VScrolling ||
- mx == WindowWidth(wnd)-1)) {
-
- /* -------- in the right border ------- */
- if (my == 0 || my == ClientHeight(wnd)+1)
- /* ------ above or below the scroll bar ---- */
- break;
-
- /* ---------- in the scroll bar ----------- */
-
- VScrolling = TRUE;
-
- if (my == 1) {
- /* -------- top scroll button --------- */
- SendMessage(wnd, SCROLL, FALSE, 0);
- return TRUE;
- }
- if (my == ClientHeight(wnd)) {
- /* -------- bottom scroll button --------- */
- SendMessage(wnd, SCROLL, TRUE, 0);
- return TRUE;
- }
- if (my-1 != wnd->VScrollBox) {
- int dir = my-1 > wnd->VScrollBox;
-
- while (dir ? (my-1 > wnd->VScrollBox) :
- (my-1 < wnd->VScrollBox)) {
- if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
- break;
- SendMessage(wnd, SCROLL, dir, 0);
- }
- return TRUE;
- }
- }
- if (TestAttribute(wnd, HSCROLLBAR) &&
- (HScrolling || my == WindowHeight(wnd)-1)) {
- /* -------- in the bottom border ------- */
- if (mx == 0 || my == ClientWidth(wnd)+1)
- /* ------ outside the scroll bar ---- */
- break;
-
- HScrolling = TRUE;
-
- if (mx == 1) {
- SendMessage(wnd, HORIZSCROLL, FALSE, 0);
- return TRUE;
- }
- if (mx == WindowWidth(wnd)-2) {
- SendMessage(wnd, HORIZSCROLL, TRUE, 0);
- return TRUE;
- }
- if (mx-1 != wnd->HScrollBox) {
- int dir = mx-1 > wnd->HScrollBox;
- while (dir ? (mx-1 > wnd->HScrollBox) :
- (mx-1 < wnd->HScrollBox)) {
- if (!SendMessage(NULLWND, TESTMOUSE, 0, 0))
- break;
- SendMessage(wnd, HORIZSCROLL, dir, 0);
- }
- return TRUE;
- }
- }
- break;
- case BUTTON_RELEASED:
- HScrolling = VScrolling = FALSE;
- break;
- case SCROLL:
- if (isVisible(wnd)) {
- if (p1 == 0) {
- if (wnd->wtop == 0)
- return FALSE;
- }
- else if (wnd->wtop+ClientHeight(wnd) >= wnd->wlines)
- return FALSE;
- if (p1)
- wnd->wtop++;
- else
- --wnd->wtop;
- SendMessage(wnd, PAINT, 0, 0);
- return TRUE;
- }
- break;
- case HORIZSCROLL:
- if (p1 == 0 && wnd->wleft == 0)
- return FALSE;
- if (p1) {
- if (wnd->wleft + ClientWidth(wnd)-1 >= wnd->textwidth)
- return FALSE;
- wnd->wleft++;
- }
- else
- --wnd->wleft;
- SendMessage(wnd, PAINT, 0, 0);
- return TRUE;
- case PAINT:
- if (isVisible(wnd) && wnd->wlines) {
- RECT rc;
- int y;
-
- if ((RECT *)p1 == NULL)
- rc = SetRect(0, 0, ClientWidth(wnd)-1,
- ClientHeight(wnd)-1);
- else
- rc = *(RECT *)p1;
-
- for (y = RectTop(rc); y <= RectBottom(rc); y++) {
- if (y < wnd->wlines-wnd->wtop)
- WriteTextLine(wnd, &rc, y, FALSE);
- else {
- char line[SCREENWIDTH];
- memset(line, ' ', sizeof line);
- line[RectRight(rc)+1] = '\0';
- SetStandardColor(wnd);
- writeline(wnd, line+RectLeft(rc),
- RectLeft(rc), y, FALSE);
- }
- }
- if (TestAttribute(wnd, VSCROLLBAR)) {
- int pagelen = wnd->wlines - ClientHeight(wnd);
- int barlen = ClientHeight(wnd)-2;
- int lines_tick;
-
- if (pagelen < 1)
- wnd->VScrollBox = 1;
- else {
- if (pagelen > barlen)
- lines_tick = pagelen / barlen;
- else
- lines_tick = barlen / pagelen;
- wnd->VScrollBox = 1 + (wnd->wtop / lines_tick);
- if (wnd->VScrollBox > ClientHeight(wnd)-2 ||
- wnd->wtop + ClientHeight(wnd) >= wnd->wlines)
- wnd->VScrollBox = ClientHeight(wnd)-2;
- }
- SendMessage(wnd, BORDER, p1, 0);
- }
- if (TestAttribute(wnd, HSCROLLBAR)) {
- int pagewidth = wnd->textwidth - ClientWidth(wnd);
- int barlen = ClientWidth(wnd)-2;
- int chars_tick;
-
- if (pagewidth < 1)
- wnd->HScrollBox = 1;
- else {
- if (pagewidth > barlen)
- chars_tick = pagewidth / barlen;
- else
- chars_tick = barlen / pagewidth;
- wnd->HScrollBox = 1 + (wnd->wleft / chars_tick);
- if (wnd->HScrollBox > ClientWidth(wnd)-2 ||
- wnd->wleft + ClientWidth(wnd) >= wnd->textwidth)
- wnd->HScrollBox = ClientWidth(wnd)-2;
- }
- SendMessage(wnd, BORDER, p1, 0);
- }
- return FALSE;
- }
- break;
- case CLOSE_WINDOW:
- SendMessage(wnd, CLEARTEXT, 0, 0);
- break;
- default:
- break;
- }
- return BaseWndProc(TEXTBOX, wnd, msg, p1, p2);
- }
-
- char *TextLine(WINDOW wnd, int selection)
- {
- char *cp = wnd->text;
- if (selection == -1)
- return NULL;
- while (selection--) {
- while (*cp != '\n')
- cp++;
- cp++;
- }
- return cp;
- }
-
- static char *GetTextLine(WINDOW wnd, int selection)
- {
- char *line;
- int len = 0;
- char *cp, *cp1;
- cp = cp1 = TextLine(wnd, selection);
- while (*cp && *cp != '\n') {
- len++;
- cp++;
- }
- line = malloc(len+6);
- if (line != NULL) {
- memmove(line, cp1, len);
- line[len] = '\0';
- }
- return line;
- }
-
- void WriteTextLine(WINDOW wnd, RECT *rcc, int y, int reverse)
- {
- int len = 0;
- int dif = 0;
- char line[100];
- RECT rc;
- char *lp, *svlp;
- int lnlen;
- int i;
- int trunc = FALSE;
-
- lp = svlp = GetTextLine(wnd, wnd->wtop+y);
- lnlen = LineLength(lp);
-
- /* -------- insert block color change controls ------- */
- if (BlockMarked(wnd)) {
- int bbl = wnd->BlkBegLine;
- int bel = wnd->BlkEndLine;
- int bbc = wnd->BlkBegCol;
- int bec = wnd->BlkEndCol;
- int by = y+wnd->wtop;
-
- if (bbl > bel) {
- swap(bbl, bel);
- swap(bbc, bec);
- }
- if (bbl == bel && bbc > bec)
- swap(bbc, bec);
-
- if (by >= bbl && by <= bel) {
- /* ------ the block includes this line ----- */
- int blkbeg = 0;
- int blkend = lnlen;
- if (!(by > bbl && by < bel)) {
- /* --- the entire line is not in the block --- */
- if (by == bbl)
- /* ---- the block begins on this line ---- */
- blkbeg = bbc;
- if (by == bel)
- /* ---- the block ends on this line ---- */
- blkend = bec;
- }
- memmove(lp+blkend+1, lp+blkend, strlen(lp+blkend)+1);
- lp[blkend] = RESETCOLOR;
- memmove(lp+blkbeg+3, lp+blkbeg, strlen(lp+blkbeg)+1);
- lp[blkbeg] = CHANGECOLOR;
- SetReverseColor(wnd);
- lp[blkbeg+1] = foreground | 0x80;
- lp[blkbeg+2] = background | 0x80;
- lnlen += 4;
- }
- }
-
- for (i = 0; i < wnd->wleft+3; i++)
- if (*(unsigned char *)(lp + i) == RESETCOLOR)
- break;
- if (i < wnd->wleft+3) {
- if (wnd->wleft+4 > lnlen)
- trunc = TRUE;
- else
- lp += 4;
- }
- else {
- for (i = 0; i < wnd->wleft; i++) {
- if (*(unsigned char *)(lp + i) == CHANGECOLOR) {
- *(lp+wnd->wleft+2) = *(lp+i+2);
- *(lp+wnd->wleft+1) = *(lp+i+1);
- *(lp+wnd->wleft) = *(lp+i);
- break;
- }
- }
- }
-
- if (!trunc) {
- if (lnlen < wnd->wleft)
- lnlen = 0;
- else
- lp += wnd->wleft;
-
- if (rcc == NULL)
- rc = SetRect(0, 0, ClientWidth(wnd)-1, ClientHeight(wnd)-1);
- else
- rc = *rcc;
-
- if (y < rc.tp || y > rc.bt)
- return;
-
- if (lnlen > RectLeft(rc)) {
- lp += RectLeft(rc);
- lnlen = LineLength(lp);
- len = min(lnlen, RectWidth(rc));
- lnlen = LineLength(lp);
- dif = strlen(lp) - lnlen;
- len += dif;
- if (len > 0)
- strncpy(line, lp, len);
- }
- }
-
- while (len < RectWidth(rc)+dif)
- line[len++] = ' ';
- line[len] = '\0';
-
- dif = 0;
- if (reverse) {
- char *cp = line;
- SetReverseColor(wnd);
- while ((cp = strchr(cp, CHANGECOLOR)) != NULL) {
- cp += 2;
- *cp++ = background | 0x80;
- }
- if (*(unsigned char *)line == CHANGECOLOR)
- dif = 3;
- }
- else
- SetStandardColor(wnd);
- writeline(wnd, line+dif, RectLeft(rc), y, FALSE);
- if (svlp != NULL)
- free(svlp);
- }
-
- void SetTextBlock(WINDOW wnd, int l1, int c1, int l2, int c2)
- {
- wnd->BlkBegLine = l1;
- wnd->BlkBegCol = c1;
- wnd->BlkEndLine = l2;
- wnd->BlkEndCol = c2;
- }
-